home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d8 / pdriver5.arc / 3C505.ASM < prev    next >
Assembly Source File  |  1989-12-17  |  19KB  |  829 lines

  1. version    equ    0
  2.  
  3.     include    defs.asm    ;SEE ENCLOSED COPYRIGHT MESSAGE
  4.  
  5. ; PC/FTP Packet Driver Source, conforming to version 1.08 of spec
  6. ; Krishnan Gopalan and Gregg Stefancik, Clemson Univesity Engineering
  7. ; Computer Operations.
  8. ; Date: September 1, 1989
  9. ; Portions of the code have been adapted from the 3c505 driver for NCSA
  10. ; Telnet by Bruce Orchard and later modified by Warren Van Houten and krus
  11. ; @diku.dk.
  12.  
  13. ; Permission is granted to any individual or institution to use,copy,
  14. ; modify or redistribute this software provided this notice is retained.
  15. ; The authors make no guarantee to the suitability of the software for
  16. ; any purpose. Any damage caused by using this program is the responsibility
  17. ; of the user and not the authors. 
  18.  
  19. code    segment    byte public
  20.     assume    cs:code, ds:code
  21.  
  22. ;    3c505 card definitions
  23. ;control register    bit definitions
  24. EN_ATTN            equ    0200q
  25. EN_FLSH_DATA        equ    0100q
  26. EN_DMA_ENABLE        equ    0040q
  27. EN_TO_HOST        equ    0020q
  28. EN_TERMINAL_CNT_ENBLE     equ    0010q
  29. EN_COMMAND_ENABLE    equ    0004q
  30. EN_HSF2            equ    0002q
  31. EN_HSF1            equ    0001q
  32.  
  33. ;status register    bit definitions
  34.  
  35. EN_DATA_READY        equ    0200q
  36. EN_HOST_COMMAND_EMPTY    equ    0100q
  37. EN_ADAPTER_COMMAND_FULL equ    0040q
  38. EN_TO_HOST        equ    0020q
  39. EN_DMA_DONE        equ    0010q
  40. EN_ASF3            equ    0004q
  41. EN_ASF2            equ    0002q
  42. EN_ASF1            equ    0001q
  43. ; auxiliary dma register  bit definition
  44. EN_BURST        equ    0001q
  45.  
  46. ; timeout values
  47. SECOND        EQU    18
  48. RESDEL        EQU    3
  49. RESTO        EQU    15*SECOND
  50. CMDBTO        EQU    3
  51. CMDCTO        EQU    3
  52. RETRYDELAY      EQU    3
  53. RCMDTO        EQU    3
  54. RESPTO        EQU    3
  55.  
  56. ;     bios data area
  57. bios_data    segment    at 40h
  58. org    06ch
  59. timer_low    dw    ?
  60. bios_data    ends
  61.  
  62. ;port addresses
  63. ECOMMAND    equ    0
  64. ESTATUS     equ    2
  65. EDATA         equ    4
  66. ECONTROL     equ    6
  67.  
  68. recvbuf        db  4096 dup(?)        ; size of receive buffer
  69. rbufct        dw    ?        ; recv buffer count
  70.  
  71. pcblen        dw     ?        ; length of pcb
  72. pcbaddr        dw    ?        ; address of pcb
  73.  
  74. lastcon        db    ?        ; last control to board
  75. cmdlen        dw    ?        ; length of command
  76.  
  77. cbsh        equ    50
  78. cbs        equ    cbsh*2    
  79.  
  80. icmdb        db    cbs dup(?)
  81. icmd        db    cbsh dup(?)
  82.  
  83. fconc        db    0    ; flag configure 82586
  84. fgeth        db    0    ; flag:get ethernet address
  85. fseth        db    0    ; flag:set ethernet address
  86. fxmit        db    0    ; flag:transmit packet
  87.  
  88. cconc        db    02h    ; command configure 82586
  89.         db    2    ; 2 more bytes
  90.         dw    1    ; receive broadcasts
  91.  
  92. rconc        db    2 dup(?);Response; configure
  93. rconc_st    dw    ?    ; status
  94.  
  95. cgeth        db    03h    ; command get ethernet address
  96.         db    00    ; no more bytes
  97.  
  98. txmit        db    09h    ; command ; transmit packet
  99.         db    06    ; 6 more bytes
  100. tx_offset    dw    ?    ; offset of host transmit buffer 
  101. tx_segment    dw    ?    ; segment of host transmit buffer 
  102. tx_length    dw    ?    ; packet length
  103.  
  104. rxmit        db    2 dup(?); Response tx packet
  105. rx_offset    dw    ?    ; buffer offset
  106. rx_segment    dw    ?    ; buffer segment
  107. rx_status    dw    ?    ; completion status
  108. rx_cstatus    dw    ?    ; 82586 status
  109.  
  110. rgeth        db    2 dup(?); Response get Ethernet address
  111. rgeth_ad    db    6 dup(?); -- address
  112.  
  113. cseth        db    10h    ; command :set station address
  114.         db    6    ; 6 more bytes
  115. cseth_ad    db    6 dup(?); ethernet address
  116.  
  117. rseth        db    2 dup(?); response set ethernet address
  118. rseth_status    dw    ?    ; status
  119.  
  120. crecv        db    08h    ; command receive
  121.         db    08    ; 8 more bytes
  122. crecv_offset    dw    ?    ; buffer offset
  123. crecv_segment    dw    ?    ; buffer segment
  124. crecv_length    dw    ?    ; buffer length
  125. crecv_timeout    dw    ?    ; timeout
  126.  
  127. rr        db    2 dup(?); Response; receive
  128. rr_offset    dw    ?    ; buffer offset
  129. rr_segment    dw    ?    ; buffer segment
  130. rr_dmalen    dw    ?    ; buffer dmalen
  131. rr_length    dw    ?    ; packet length
  132. rr_status    dw    ?    ; completion status
  133. rr_rstatus    dw    ?    ; 82586 receive status
  134. rr_time        dd    ?    ; time tag
  135.         
  136. public    int_no,io_addr,mem_base
  137.  
  138. int_no     db    2,0,0,0            ;must be four bytes long for get_number.
  139. io_addr dw    0300h,0            ; io addr for card(jumpers)
  140. mem_base dw    0d000h,0        ; shared memory address(software)
  141.  
  142. public    driver_class, driver_type, driver_name 
  143.  
  144. driver_class    db    1        ;from the packet spec 
  145. driver_type    db    2        ;from the packet spec 
  146. driver_name    db    '3C505',0    ;name of the driver.  
  147.  
  148.     public    rcv_modes
  149. rcv_modes    dw    4        ;number of receive modes in our table.
  150.         dw    0,0,0,rcv_mode_3
  151.  
  152. public    send_pkt 
  153. send_pkt:
  154. ;enter with ds:si -> packet, cx = packet length.
  155. ;exit with nc if ok, or else cy if error, dh set to error number.
  156.     assume    ds:nothing
  157.  
  158.     push    si            ; save si for  lodsw
  159.     push    ds            ; save ds
  160.     push    es            ; save es for timer
  161.     push    cs            ;
  162.     pop    ds            ; cs = ds align
  163.     
  164.     mov    ax,seg timer_low    ; ax->time
  165.     mov    es,ax            ; es->bios_data
  166.     
  167.     mov    tx_segment,ds        ;tx->data
  168.     mov    tx_offset,si        ;tx_offset ->segment offset 
  169.  
  170.     mov    ax,cx            ; save cx
  171.     cmp    ax,60            ; compare with minimum limit
  172.     jnb    pkt_ok            ; go if ok 
  173.     mov    ax,60            ; make length minimum allowed
  174. pkt_ok:
  175.     inc    ax            ; round up
  176.     sar    ax,1            ; divide by 2
  177.     shl    ax,1            ; multiply by 2
  178.     mov    tx_length,ax        ; put in request
  179.     
  180.     mov    fxmit,0            ; clear response received flag
  181.  
  182.     mov    si, offset txmit    ; si->request(pcb)
  183.     mov    ax,8            ;length of pcb 
  184.  
  185.     call    outpcb            ; send command to board
  186.  
  187.     mov    cx,tx_length
  188.     sar    cx,1
  189.  
  190.     pop    es
  191.     pop    ds
  192.     pop    si
  193.  
  194. tx_1:
  195.  
  196.     lodsw
  197.  
  198.     loadport
  199.     setport    EDATA
  200.     out    dx,ax            ; output word
  201.     setport    ESTATUS
  202. tx_2:
  203.     in    al,dx            ; get status
  204.     test    al, EN_DATA_READY    ; ready for next word ?
  205.     jz    tx_2            ;no
  206.  
  207.     dec    cx            ; count word
  208.     jnz    tx_1            ; loop thru buffer
  209.  
  210. tx_3:
  211.     test    fxmit,0ffh        ; is transmit over
  212.     jz    tx_3            ; no
  213.     ret
  214.  
  215.     public    get_address
  216.  
  217.  
  218. get_address:
  219. ;get the address of the interface.
  220. ;enter with es:di -> place to get the address, cx = size of address buffer.
  221. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  222.     assume    ds:code
  223.     push    es
  224.     push    di
  225.     mov    ax, seg    timer_low 
  226.     mov    es,ax
  227.     cmp    cx, EADDR_LEN        ; does caller want reasonable length?
  228.     jb    get_addr_fail        ; no , fails
  229.     mov    si,offset cgeth        ; si->pcb address
  230.     mov    ax,2            ; length of pcb
  231.     mov    fgeth,0            ; clear response received flag
  232.  
  233.     call    outpcb        
  234.  
  235.     mov    ax,es:timer_low        ; current time->ax
  236.     add    ax,RESTO        ; add wait time
  237. get_addr_1:
  238.     test    fgeth,0ffh        ; answered?
  239.     jnz    get_addr_2        ; yes
  240.     cmp    ax,es:timer_low        ; expired?
  241.     ja    get_addr_1        ; test again
  242.     jmp    get_addr_fail        ; go return
  243.  
  244. get_addr_2:
  245.     pop    di
  246.     pop    es
  247.     cld                ; make sure of string operation
  248.     mov    si,offset rgeth_ad    ; load source of address
  249.     mov    cx,EADDR_LEN        ; return length of address
  250.     rep    movsb            ; copy address
  251.     mov    cx,EADDR_LEN        ; return length of address
  252.     clc
  253.     ret
  254. get_addr_fail:
  255.     add sp,4
  256.     stc
  257.     ret
  258.  
  259.     public    set_address
  260.  
  261. set_address:
  262. ;enter with ds:si -> Ethernet address, CX = length of address.
  263. ;exit with nc if okay, or cy, dh=error if any errors.
  264.     assume    ds:nothing
  265.     mov    ax, seg timer_low
  266.     mov    es,ax
  267.     cmp    cx, EADDR_LEN        ; check if address ok
  268.     je    set_addr_1    
  269.     mov    dh,BAD_ADDRESS        ; don't like length
  270.     stc
  271.     ret
  272. set_addr_1:
  273.     mov    di,offset cseth_ad    ;di->destination offset
  274.     rep    movsb            ; return address
  275.     mov    si,offset cseth        ; si->request ethernet address
  276.     mov    ax,8            ; request length -> ax
  277.     mov    fseth,0            ; clear response received flag
  278.     call     outpcb            ; send the pcb
  279.     mov    ax,es:timer_low        ; current time->ax
  280.     add    ax,RESTO        ; add response time
  281. set_addr_2:
  282.     test    fseth,0ffh        ; pcb answered?
  283.     jnz    set_addr_3
  284.     cmp    ax,es:timer_low        ; has time expired
  285.     ja    set_addr_2        ; no, go back
  286.     stc                ; error
  287.     ret
  288. set_addr_3:
  289.     mov    cx,EADDR_LEN        ;return their address length.
  290.     clc
  291.     ret
  292.  
  293. rcv_mode_3:
  294. ;receive mode 3 is the only one we support, so we don't have to do anything.
  295.     ret
  296.  
  297.  
  298.     public    set_multicast_list
  299. set_multicast_list:
  300. ;enter with es:di ->list of multicast addresses, cx = number of bytes.
  301. ;return nc if we set all of them, or cy,dh=error if we didn't.
  302.     mov    dh,NO_MULTICAST
  303.     stc
  304.     ret
  305.  
  306.  
  307.     public    get_multicast_list
  308. get_multicast_list:
  309. ;return with nc, es:di ->list of multicast addresses, cx = number of bytes.
  310. ;return cy, NO_ERROR if we don't remember all of the addresses ourselves.
  311. ;return cy, NO_MULTICAST if we don't implement multicast.
  312.     mov    dh,NO_MULTICAST
  313.     stc
  314.     ret
  315.  
  316.  
  317.     public    reset_interface
  318. reset_interface:
  319. ;reset the interface.
  320.     assume    ds:code
  321.     mov    bx,seg timer_low
  322.     mov    es,bx
  323.     mov    al, EN_ATTN OR EN_FLSH_DATA    ; hard reset command
  324.     loadport
  325.     setport    ECONTROL
  326.     out    dx,al                ; do reset
  327.     mov    ax,es:timer_low            ; current timer ->ax
  328.     add    ax,RESDEL            ; add reset delay
  329. rst1:
  330.     cmp    ax,es:timer_low            ; compare to current time
  331.     ja    rst1                ; wait for reset
  332.     mov    al,EN_COMMAND_ENABLE        ; command interrupt enable
  333.     mov    lastcon,al            ; save last command
  334.     out    dx,al                ; release reset
  335.     mov    ax,es:timer_low            ; current timer->ax
  336.     add    ax,RESDEL
  337. rst2:
  338.     cmp    ax,es:timer_low
  339.     ja    rst2                ; wait to start reset
  340.     mov    bx,es:timer_low            ; current timer->bx
  341.     add    bx,RESTO            ; add time out
  342. rst3:
  343.     call getstat                ; getstatus    
  344.     and    ax,EN_ASF1 OR EN_ASF2        ; 
  345.     cmp    ax,EN_ASF1 OR EN_ASF2        ;  both on ?
  346.     jne     resdone
  347.     cmp    bx,es:timer_low            ; long enough?
  348.     ja    rst3                ; no
  349.     ret
  350. resdone:
  351.     ret
  352. ;called when we want to determine what to do with a received packet.
  353. ;enter with cx = packet length, es:di -> packet type.
  354.     extrn    recv_find: near
  355.  
  356. ;called after we have copied the packet into the buffer.
  357. ;enter with ds:si ->the packet, cx = length of the packet.
  358.     extrn    recv_copy: near
  359.  
  360.     extrn    count_in_err: near
  361.     extrn    count_out_err: near
  362.  
  363.     public    recv
  364. recv:
  365. ;called from the recv isr.  All registers have been saved, and ds=cs.
  366. ; all interrupts come here
  367. ;Upon exit, the interrupt will be acknowledged.
  368.     assume    ds:code
  369.     ;sti
  370.     cld
  371. recv1:
  372.     loadport
  373.     setport    ESTATUS
  374.     in    al,dx                ; read flags
  375.     and    al,EN_ADAPTER_COMMAND_FULL    ; 
  376.     jnz    recv2                ; yes,full
  377.     jmp    interrupt_done    
  378. ;there might be a response, clear flags to check for response
  379. recv2:
  380.     mov    bx,es:timer_low        ; current time->bx
  381.     ;mov    es,bx
  382.     add    bx,RCMDTO            ; incoming command time out
  383.  
  384.     mov    al,lastcon            ; last control->ax
  385.     and    al,NOT (EN_HSF1 OR EN_HSF2)    ; clear flags
  386.     mov    lastcon,al
  387.  
  388.     loadport
  389.     setport    ECONTROL
  390.     out    dx,al                ; clear flags in cntl reg
  391.  
  392.     mov    di,offset icmdb            ; di->incoming command buffer
  393.  
  394. recv3:
  395.     loadport
  396.     setport    ESTATUS
  397.     in    al,dx                ; status->al
  398.  
  399.     mov    cx,ax                ; status->cx
  400.     test    al,EN_ADAPTER_COMMAND_FULL    ; is adapter register full
  401.     jnz    recv4                ; yes go ahead to read from
  402.     cmp    bx,es:timer_low            ; is time up ? 
  403.  
  404.     ja    recv3                ; give some more time
  405.     jmp    int1                ; give up
  406. recv4:
  407.     loadport
  408.     setport    ECOMMAND
  409.     in    al,dx                ; get command byte
  410.     and    cl,EN_ASF1 OR EN_ASF2        
  411.     cmp    cl,EN_ASF1 OR EN_ASF2        ; both on?
  412.     je    recv5                ; end of command
  413.     mov    [di],al                ;save byte
  414.     inc    di                ;inc    di 
  415.     mov    ax,di                ; current pointer->ax
  416.     sub    ax,offset icmdb            ; - start of buffer
  417.     cmp    ax,cbs                ; full?
  418.     jl    recv3
  419.  
  420.     mov    si,(offset icmdb)+cbsh        ; si->middle of buffer
  421.     mov    di,offset icmdb            ; di->start of buffer
  422.     mov    cx,cbsh                ; size of half buffer->cx
  423.     push    ds
  424.     pop    es
  425.     rep    movsb
  426.  
  427.     jmp    recv3                ; loop for more bytes
  428. recv5:
  429.     push    ds
  430.     pop    es
  431.     mov    ah,0
  432.     mov    cmdlen,ax            ; save cmdlen
  433.     mov    si,di 
  434.     sub    si,cmdlen
  435.     mov    di,offset icmd    
  436.     mov    cx,cmdlen
  437.  
  438.     rep movsb                ; copy
  439.  
  440.     mov    al,icmd                ; check
  441.  
  442.     cmp    al,32h                ; Configure?
  443.     je    respconfig
  444.  
  445.     cmp    al,33h                ; get ethernet address?
  446.     je    respgetaddr            ; yes
  447.  
  448.     cmp    al,39h                ; transmit complete?
  449.     je    transmit            ; yes
  450.  
  451.     cmp    al,40h                ; set ethernet address
  452.     je    respsetaddr            ; yes
  453.     
  454.     cmp    al,38h                ; receive complete?
  455.     je    resprecv
  456.  
  457.     jmp    int1
  458.  
  459. respconfig:
  460.  
  461.     push    ds
  462.     pop    es
  463.     mov    si,offset icmd
  464.     mov    di,offset rconc
  465.     mov    cx,2
  466.     
  467.     rep    movsw
  468.     mov    fconc,1
  469.     jmp    int1
  470.     
  471. respgetaddr:
  472.     push    ds
  473.     pop    es
  474.  
  475.     mov    si,offset icmd
  476.     mov    di,offset rgeth
  477.     mov    cx,4
  478.  
  479.     rep    movsw
  480.  
  481.     mov    fgeth,1
  482.     jmp    int1
  483.  
  484. respsetaddr:
  485.  
  486.     mov    si,offset icmd        ; si->command received
  487.     mov    di,offset cseth        ; di->set ethernet address resp
  488.     push    ds
  489.     pop    es
  490.     mov    cx,2
  491.  
  492.     rep    movsw
  493.     mov    fseth,1
  494.     jmp    int1
  495.  
  496. transmit:
  497.     mov    si,offset icmd            ; si->command received
  498.     mov    di,offset rxmit            ; response,transmit packet
  499.     push    ds
  500.     pop    es
  501.     mov    cx,5                ; response length->cx
  502.     rep    movsw
  503.  
  504.     mov    fxmit,1                ; response received
  505.     jmp    int1                ; return from interrupt
  506.  
  507. resprecv:
  508.     mov    si,offset icmd            ; si->command received
  509.     mov    di,offset rr            ; di->receive response
  510.     push    ds
  511.     pop    es
  512.     mov    cx,9                ; response length->cx
  513.     
  514.     rep    movsw                ; move response
  515.     mov    di,offset recvbuf        ; di->receive buffer
  516.     mov    ax,rr_length            ; message size->ax
  517.     inc    ax                ; round up
  518.     shr    ax,1                ; convert to words
  519.     shl    ax,1                ; convert to characters
  520.     mov    rr_length,ax            ; ax->message length
  521.  
  522.     mov    cx,ax                ; message length->cx
  523.     shr    cx,1                ; convert to words
  524.  
  525.     mov    al,lastcon            ; lastcontrol->al
  526.     or    al,EN_TO_HOST OR EN_HSF1    ; set direction & ack    
  527.     mov    lastcon,al            ; response
  528.  
  529.     loadport
  530.     setport    ECONTROL
  531.     out    dx,al                ; pass direction
  532.     
  533.     setport ESTATUS
  534.  
  535. resprecv_1:
  536.  
  537.     in    al,dx                ; get status
  538.     test    al,EN_DATA_READY        ; data ready ?
  539.     jz    resprecv_1
  540.  
  541.     setport    EDATA                ; data word->ax
  542.     in    ax,dx                ; get word
  543.     stosw                    ; store word in buffer
  544.  
  545.     setport    ESTATUS
  546.     dec    cx                ; count word
  547.     jnz    resprecv_1            ; loop if more words
  548.  
  549.     mov    al,lastcon
  550.     and    al,NOT (EN_TO_HOST OR EN_HSF1)
  551.     mov    lastcon,al
  552.  
  553.     loadport                ; dx->control register
  554.     setport    ECONTROL
  555.     out    dx,al
  556.  
  557.     mov    cx,rr_length            ; cx->packet length
  558.  
  559.     push    cs                ; align cs and ds
  560.     pop    ds
  561.  
  562.     mov    di,offset recvbuf        ; reset di to beginning
  563.     add    di,EADDR_LEN+EADDR_LEN        ; point to type field
  564.                         ; of buffer
  565.     assume    ds:code
  566.  
  567.     call    recv_find            ; first call
  568.  
  569.     assume    ds:nothing
  570.     mov    ax,es                ; ax->es
  571.     or    ax,di                ; is es=di=0?
  572.     je    rcv_no_copy
  573.  
  574.     mov    cx,rr_length            ; cx->packet length
  575.     push    cx
  576.     push    es
  577.     push    di
  578.  
  579.     mov    si,offset recvbuf        ; prepare to copy the packet
  580.     rep    movsb                ; copy
  581.  
  582.     pop    si
  583.     pop    ds
  584.     pop    cx
  585.  
  586.     call    recv_copy            ; second call 
  587. rcv_no_copy:
  588.     push    cs
  589.     pop    ds
  590.     call    anotherrecv            ; start another recv
  591. int1:
  592.     jmp    recv1
  593.  
  594. interrupt_done:
  595.     ret
  596.  
  597. ;*****************************OUTPCB***********************************
  598. ;outpcb     send pcb to board, retry until accepted
  599. ; entry    ax = number of bytes in pcb
  600. ;    si = address of pcb
  601. outpcb    proc     near
  602.     mov    pcblen,ax        ; save pcb length
  603.     mov    pcbaddr,si        ; save pcb address
  604. pcb_0:
  605.     mov    cx,pcblen        ;length->cx
  606.     mov    si,pcbaddr        ; address->si
  607.     cli                ; stop interrupts
  608.     mov    al,lastcon        ; save last command
  609.     and    al, NOT (EN_HSF1 OR EN_HSF2); clear flags
  610.     mov    lastcon,al
  611.     sti                ; enable interrupts
  612.     loadport
  613.     setport    ECONTROL
  614.     out    dx,al            ; send control
  615.     setport    ECOMMAND
  616. pcb_1:
  617.     mov    al,[si]            ; 
  618.     out    dx,al            ; send command byte
  619.     mov    bx,es:timer_low        ; current timer
  620.     add    bx,CMDBTO        ; add time out
  621. chk_hcre:
  622.     call    getstat
  623.     and    al, EN_HOST_COMMAND_EMPTY    ; command accepted
  624.     jne    pcb_2                ; go on
  625.     cmp    bx,es:timer_low            ; 
  626.     ja    chk_hcre            ; time is still left
  627.     jmp    cmdretry            ; retry command
  628. pcb_2:
  629.     inc    si                ; increment source pointer
  630.     dec    cx                ; count byte
  631.     jg    pcb_1                ; loop         
  632.     loadport
  633.     setport    ECONTROL
  634.     cli                    ; disable interrupts
  635.     mov    al,lastcon            ; last control -> al
  636.     or    al,(EN_HSF1 OR EN_HSF2)        ; set end of command
  637.     mov    lastcon,al            ; save last control
  638.     out    dx,al                ; send flag bits
  639.     setport    ECOMMAND
  640.     mov    ax,pcblen
  641.     out    dx,al                ; send pcb length
  642.     sti                    ; enable interrupts
  643.     mov    bx,es:timer_low            ; current time->bx
  644.     add    bx,CMDCTO            ; time out for acceptance
  645. pcb_3:
  646.     call    getstat
  647.     and    al,(EN_ASF1 OR EN_ASF2)        ; just keep status flags
  648.     cmp    al,1                ; accepted
  649.     je    cmdaccept
  650.     cmp    al,2
  651.     je    cmdretry
  652.     cmp    bx,es:timer_low
  653.     ja    pcb_3
  654.  
  655. cmdretry:
  656.     mov    ax,es:timer_low            ; current time->ax
  657.     add    ax,RETRYDELAY            ;add retry delay
  658. pcb_4:
  659.     cmp    ax,es:timer_low
  660.     ja    pcb_4
  661.     jmp    pcb_0
  662.  
  663. cmdaccept:
  664.     cli
  665.     mov    al,lastcon
  666.     and    al, NOT (EN_HSF1 OR EN_HSF2)    ; turn off end of command flag
  667.     mov    lastcon,al            ; save last control
  668.     sti                    ; enable interrupts
  669.     loadport
  670.     setport    ECONTROL
  671.     out    dx,al                ; pass control byte
  672.     ret    
  673. outpcb    endp
  674. ;*************get status of board***********************
  675. getstat        proc    near
  676.     push    bx
  677.     push    dx
  678.     loadport
  679.     setport    ESTATUS
  680.  
  681. stat_1:
  682.     in    al,dx            ; get status into al
  683.     mov    bl,al            ; save al
  684.     in    al,dx            ; get status again
  685.     cmp    al,bl            ; same status ?
  686.     jne    stat_1
  687.     pop    dx
  688.     pop    bx
  689.     ret
  690. getstat    endp
  691.  
  692. ; UPDATE BUFFER POINTERS AND ISSUE ANOTHER RECV
  693. ;    update recv 
  694. anotherrecv    proc    near
  695.     mov    ax,rbufct
  696.     mov    crecv_offset,ax
  697.     inc    ax
  698.     mov    rbufct,ax
  699.     mov    ax,10
  700.     mov    si,offset crecv
  701.  
  702.     call    outpcb
  703.     ret
  704. anotherrecv    endp
  705.  
  706.     public    recv_exiting
  707. recv_exiting:
  708. ;called from the recv isr after interrupts have been acknowledged.
  709. ;Only ds and ax have been saved.
  710.     assume    ds:nothing
  711.     ret
  712.  
  713. ;any code after this will not be kept after initialization.
  714. end_resident    label    byte
  715.  
  716.     public    usage_msg
  717. usage_msg  db  "usage: 3C505 <packet_int_no> <int_level> <io_addr> <mem_base>",CR,LF,'$'
  718.     public    copyright_msg
  719. copyright_msg    db    "Packet Driver for 3c505, version ",'0'+majver, ".",CR,LF
  720.          db    "Portions copyright 1989, Krishnan Gopalan & Gregg Stefancik.",CR,LF
  721.          db     "Clemson University Engineering Comp Ops.",CR,LF,'$'
  722. no_board_msg:
  723.     db    "3c505 apparently not present at this address.",CR,LF,'$'
  724. int_no_name    db    "Interrupt number ",'$'
  725. io_addr_name    db    "I/O port ",'$'
  726. mem_base_name    db    "Memory address ",'$'
  727.  
  728.     extrn    set_recv_isr: near
  729.  
  730. ;enter with si -> argument string, di -> word to store.
  731. ;if there is no number, don't change the number.
  732.     extrn    get_number: near
  733.  
  734.     public    parse_args
  735. parse_args:
  736.     mov    di,offset int_no
  737.     mov    bx,offset int_no_name
  738.     call     get_number
  739.     mov    di,offset io_addr
  740.     mov    bx,offset io_addr_name
  741.     call    get_number
  742.     mov    di,offset mem_base
  743.     mov    bx,offset mem_base_name
  744.     call    get_number    
  745.     ret
  746.  
  747.     public    etopen
  748. etopen:
  749. ;if all is okay,
  750. ; reset the 3c505 board takes about 15-20 seconds
  751.     loadport
  752.     setport    ECONTROL 
  753.     mov    al,EN_ATTN OR EN_FLSH_DATA    ; reset command
  754.     out    dx,al                ; do reset
  755.     mov    ax,seg    timer_low
  756.     mov    es,ax
  757.     mov    ax,es:timer_low
  758. reset1:
  759.     cmp    ax,es:timer_low            ; current time->ax
  760.     ja    reset1                ; wait for reset to propagate
  761.     mov    al,EN_COMMAND_ENABLE        ; command interrupt enable
  762.     mov    lastcon,al            ; save last command
  763.     out    dx,al                ; release reset
  764.     mov    ax,es:timer_low            ; current timer->ax
  765.     add    ax,RESDEL            ; time to wait
  766. reset2:
  767.     cmp    ax,es:timer_low            ; compare to current time
  768.     ja    reset2                ; 
  769.     mov    bx,es:timer_low            ; 
  770.     add    bx,RESTO
  771. reset3:
  772.     call    getstat
  773.     and    ax, EN_HSF1 OR EN_HSF2
  774.     cmp    ax,EN_HSF1 OR    EN_HSF2
  775.     jne    resetdone
  776.     cmp    bx,es:timer_low        
  777.     ja    reset3
  778.     jmp    openfail            ; open failed
  779.  
  780. resetdone:
  781.     call    set_recv_isr            ;install the interrupt handler
  782.  
  783. ;Tell the 3c505 board to receive packets
  784.     mov    si,offset cconc
  785.     mov    ax,4
  786.     mov    fconc,0
  787.  
  788.     call    outpcb
  789.  
  790.     mov    ax,es:timer_low
  791.     add    ax,RESTO    
  792.  
  793. open_1:
  794.     test    fconc,0ffh
  795.     jnz    setuprecv
  796.  
  797.     cmp    ax,es:timer_low
  798.     ja    open_1
  799.  
  800. ; set up the recv buffers
  801.  
  802. setuprecv:
  803.     mov    rbufct,0            ; clear buffer counter
  804.     mov    crecv_length,1600        ; buffer length,1600
  805.  
  806. startrecv:
  807.     mov    ax,rbufct            ; buffer counter->ax
  808.     mov    crecv_offset,ax            ; buf no used as offset
  809.     inc    ax                ; count buffer
  810.     mov    rbufct,ax
  811.     mov    ax,10                ; length of pcb
  812.     mov    si,offset crecv            ;si->command receive
  813.  
  814.     call    outpcb                ; pass the pcb
  815.     mov    ax,rbufct
  816.     cmp    ax,10
  817.     jl    startrecv
  818.  
  819.     mov    dx,offset end_resident
  820.     clc
  821.     ret
  822.  
  823. ;if we got an error,
  824. openfail:
  825.     stc
  826.     ret
  827. code    ends
  828.     end
  829.